﻿using System;
using System.Collections.Generic;
using System.Linq;
using ReagentStore.DAL;
using ReagentStore.ERM;
using ReagentStore.Resources.Properties;
using ReagentStore.UTL;

namespace ReagentStore.BLL
{
	public class RecordBLL : ICheckRecordStrategy
	{
		public readonly RecordDAL DALAccessor = new RecordDAL();
		private readonly Dictionary<Type, ICheckRecordStrategy> _dictChecker = new Dictionary<Type, ICheckRecordStrategy>();

		public RecordBLL()
		{
			_dictChecker.Add(typeof (IncomingRecord), new IncomingRecordChecker());
			_dictChecker.Add(typeof (OutgoingRecord), new OutgoingRecordChecker());
			_dictChecker.Add(typeof (WearRecord), new WearRecordChecker());
		}

		public void Insert(Record record)
		{
			CheckParams(record);
			DALAccessor.Insert(record);
		}

		public void Delete(Record record)
		{
			Record exist = new RecordDAL().GetEntityById(record.RecordID);
			if (exist == null)
				throw new ApplicationException(DefaultResources.RECORD_NOT_FOUND);

			bool deletable = true;
			IList<Record> records = DALAccessor.GetEntitiesByProductId(record.ProductID);

			int quantity = records.Where(r => r.Date < record.Date).Sum(r => r.Quantity());
			if (quantity < 0)
				deletable = false;
			else
				foreach (Record behind in records.Where(r => r.Date > record.Date))
				{
					quantity += behind.Quantity();

					if (quantity < 0)
					{
						deletable = false;
						break;
					}
				}

			if (deletable)
				DALAccessor.Delete(record);
			else
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);
		}

		#region Implementation of ICheckRecordStrategy

		public void CheckParams(Record record)
		{
			_dictChecker[record.GetType()].CheckParams(record);
		}

		#endregion
	}

	internal class IncomingRecordChecker : ICheckRecordStrategy
	{
		#region Implementation of ICheckRecordStrategy

		public void CheckParams(Record record)
		{
			var checkrec = record as IncomingRecord;
			if (checkrec == null)
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);

			if (checkrec.Count < 0)
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);

			Product exist = new ProductDAL().GetEntityById(checkrec.ProductID);
			if (exist == null)
				throw new ApplicationException(DefaultResources.PRODUCT_NOT_FOUND);

			checkrec.Bill = checkrec.Bill.Regular();

			if (string.IsNullOrEmpty(checkrec.Bill))
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);
		}

		#endregion
	}

	internal class OutgoingRecordChecker : ICheckRecordStrategy
	{
		#region Implementation of ICheckRecordStrategy

		public void CheckParams(Record record)
		{
			var checkrec = record as OutgoingRecord;
			if (checkrec == null)
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);

			int quantity = new RecordDAL().GetEntitiesByProductId(checkrec.ProductID).Sum(r => r.Quantity());
			if (quantity - checkrec.Count < 0)
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);

			Product exist = new ProductDAL().GetEntityById(checkrec.ProductID);
			if (exist == null)
				throw new ApplicationException(DefaultResources.PRODUCT_NOT_FOUND);

			checkrec.Recipient = checkrec.Recipient.Regular();

			if (string.IsNullOrEmpty(checkrec.Recipient))
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);
		}

		#endregion
	}

	internal class WearRecordChecker : ICheckRecordStrategy
	{
		#region Implementation of ICheckRecordStrategy

		public void CheckParams(Record record)
		{
			var checkrec = record as WearRecord;
			if (checkrec == null)
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);

			int quantity = new RecordDAL().GetEntitiesByProductId(checkrec.ProductID).Sum(r => r.Quantity());
			if (quantity - checkrec.Count < 0)
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);

			Product exist = new ProductDAL().GetEntityById(checkrec.ProductID);
			if (exist == null)
				throw new ApplicationException(DefaultResources.PRODUCT_NOT_FOUND);

			checkrec.Reason = checkrec.Reason.Regular();

			if (string.IsNullOrEmpty(checkrec.Reason))
				throw new ApplicationException(DefaultResources.RECORD_INVALID_PARAM);
		}

		#endregion
	}
}